﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Web;

namespace MvcSystemsCommander.Extensions.Security
{
    public class HashwordModel
    {
        public string Hashword { get; set; }
        public string Salt { get; set; }
    }

    public static class HashwordHelper
    {
        public static HashwordModel GetHashwordModel(string nPassword)
        {
            HashwordModel m = new HashwordModel();

            RNGCryptoServiceProvider provider = new RNGCryptoServiceProvider();
            byte[] salt = new byte[32];
            provider.GetBytes(salt);

            byte[] username = System.Text.Encoding.UTF8.GetBytes(nPassword);

            byte[] hashword = HashwordHelper.GenerateSaltedHash(username, salt);

            m.Hashword = System.Text.UTF8Encoding.UTF8.GetString(hashword);
            m.Salt = System.Text.UTF8Encoding.UTF8.GetString(salt);

            return m;
        }

        public static bool Compare(string nPassword, string nSalt, string nHashword)
        {
            byte[] bPassword = System.Text.Encoding.UTF8.GetBytes(nPassword);
            byte[] bSalt = System.Text.Encoding.UTF8.GetBytes(nSalt);
            byte[] bHashword = System.Text.Encoding.UTF8.GetBytes(nHashword);
            byte[] computed = HashwordHelper.GenerateSaltedHash(bPassword, bSalt);

            return HashwordHelper.CompareByteArrays(computed, bHashword);
        }

        private static byte[] GenerateSaltedHash(byte[] plainText, byte[] salt)
        {
            HashAlgorithm algorithm = new SHA256Managed();

            byte[] plainTextWithSaltBytes =
              new byte[plainText.Length + salt.Length];

            for (int i = 0; i < plainText.Length; i++)
            {
                plainTextWithSaltBytes[i] = plainText[i];
            }
            for (int i = 0; i < salt.Length; i++)
            {
                plainTextWithSaltBytes[plainText.Length + i] = salt[i];
            }

            return algorithm.ComputeHash(plainTextWithSaltBytes);
        }

        public static bool CompareByteArrays(byte[] array1, byte[] array2)
        {
            if (array1.Length != array2.Length)
            {
                return false;
            }

            for (int i = 0; i < array1.Length; i++)
            {
                if (array1[i] != array2[i])
                {
                    return false;
                }
            }

            return true;
        }
    }
}